package drds.binlog.store;

import drds.binlog.common.AbstractLifeCycle;
import drds.binlog.common.Authors;
import drds.binlog.common.position.ClientInfo;
import drds.binlog.common.position.LogPosition;
import drds.binlog.common.position.Position;
import drds.binlog.metadata.IMetaDataManager;
import drds.common.$;
import drds.common.Author;

import java.util.List;

/**
 * store回收机制
 */
@Author(name = Authors.LI_YANG)
public abstract class AbstractCleanUp extends AbstractLifeCycle implements CleanUp
{

    protected String destination;
    protected IMetaDataManager IMetaDataManager;
    protected boolean onAck = true;
    protected boolean onFull = false;
    protected boolean onSchedule = false;
    protected String scavengeSchedule = null;

    public void scavenge()
    {
        Position position = getLatestAckPosition(destination);
        cleanUpUntil(position);
    }

    /**
     * 找出该destination中可被清理掉的position位置
     *
     * @param destination
     */
    private Position getLatestAckPosition(String destination)
    {
        List<ClientInfo> clientInfoList = IMetaDataManager.getClientInfoList(destination);
        LogPosition result = null;
        if ($.isHasData(clientInfoList))
        {
            // 尝试找到一个最小的logPosition
            for (ClientInfo clientInfo : clientInfoList)
            {
                LogPosition position = (LogPosition) IMetaDataManager.getPosition(clientInfo);
                if (position == null)
                {
                    continue;
                }

                if (result == null)
                {
                    result = position;
                } else
                {
                    result = min(result, position);
                }
            }
        }

        return result;
    }

    /**
     * 找出一个最小的position位置
     */
    private LogPosition min(LogPosition position1, LogPosition position2)
    {
        if (position1.getLogIdentity().equals(position2.getLogIdentity()))
        {
            // 首先根据文件进行比较
            if (position1.getEntryPosition().getJournalName().compareTo(position2.getEntryPosition().getJournalName()) < 0)
            {
                return position2;
            } else if (position1.getEntryPosition().getJournalName().compareTo(position2.getEntryPosition().getJournalName()) > 0)
            {
                return position1;
            } else
            {
                // 根据offest进行比较
                if (position1.getEntryPosition().getPosition() < position2.getEntryPosition().getPosition())
                {
                    return position2;
                } else
                {
                    return position1;
                }
            }
        } else
        {
            // 不同的主备库，根据时间进行比较
            if (position1.getEntryPosition().getTimestamp() < position2.getEntryPosition().getTimestamp())
            {
                return position2;
            } else
            {
                return position1;
            }
        }
    }

    public void setOnAck(boolean onAck)
    {
        this.onAck = onAck;
    }

    public void setOnFull(boolean onFull)
    {
        this.onFull = onFull;
    }

    public void setOnSchedule(boolean onSchedule)
    {
        this.onSchedule = onSchedule;
    }

    public String getScavengeSchedule()
    {
        return scavengeSchedule;
    }

    public void setScavengeSchedule(String scavengeSchedule)
    {
        this.scavengeSchedule = scavengeSchedule;
    }

    public void setDestination(String destination)
    {
        this.destination = destination;
    }

    public void setMetaDataManager(IMetaDataManager IMetaDataManager)
    {
        this.IMetaDataManager = IMetaDataManager;
    }

}
